﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports System
Imports System.Globalization
Imports System.IO
Imports System.Linq
Imports System.Xml.Serialization
Imports System.Web

Namespace roncliProductions.LibWowArmory.Character.Achievements.Category

    Public Class CharacterAchievementsCategory
        Inherits WowArmoryData

#Region "Declarations"

        Private cacAchievements As New Schema.achievements
        Private cCategory As New Category

#End Region

        ''' <summary>
        ''' The realm the character is on
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Realm As String

        ''' <summary>
        ''' The name of the character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Name As String

        ''' <summary>
        ''' The identification number of the achievement category
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property CategoryID As Integer

        ''' <summary>
        ''' The URL that will be used to retrieve the character's achievements from the Armory
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL As String
            Get
                Return String.Format(CultureInfo.InvariantCulture, "http://www.wowarmory.com/character-achievements.xml?r={0}&n={1}&c={2}", Realm, Name, CategoryID)
            End Get
        End Property

        ''' <summary>
        ''' Indicates to the inherited class that this request does not require login
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property RequiresLogin As Boolean
            Get
                Return False
            End Get
        End Property

        ''' <summary>
        ''' The achievements for this category
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Achievements As Category
            Get
                Return cCategory
            End Get
        End Property

        ''' <summary>
        ''' A constructor to load a character's achievements by realm and character name
        ''' </summary>
        ''' <param name="strRealm"></param>
        ''' <param name="strName"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal strRealm As String, ByVal strName As String, ByVal intCategoryID As Integer)
            Realm = strRealm
            Name = strName
            CategoryID = intCategoryID
            Load()
        End Sub

        ''' <summary>
        ''' Loads the character's achievements for this category from the armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Load()
            Dim strKey As String = String.Format(CultureInfo.InvariantCulture, "LibWowArmory.CharacterAchievementsCategory.{0}.{1}.{2}", Realm, Name, CategoryID)
            If Cache.Cache(strKey) Is Nothing Then
                MyBase.Retrieve()

                Dim xsSerializer As New XmlSerializer(cacAchievements.GetType)

                Using srXML As New StringReader(MyBase.Data)
                    cacAchievements = CType(xsSerializer.Deserialize(srXML), Schema.achievements)
                End Using

                Cache.Cache.Insert(strKey, cacAchievements, Nothing, Date.UtcNow.AddDays(1), Nothing, Caching.CacheItemPriority.Normal, Nothing)
            Else
                cacAchievements = CType(Cache.Cache(strKey), Schema.achievements)
            End If

            If cacAchievements Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If
            If cacAchievements.category Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If

            ProcessCategory(cCategory, cacAchievements.category.First)
        End Sub

        Private Sub ProcessCategory(ByRef cCategoryToProcess As Category, ByRef cacCategory As Schema.category)
            For Each cacAchievement As Schema.achievement In cacCategory.achievement
                Dim aAchievement As New Achievement(cacAchievement.categoryId, cacAchievement.dateCompleted, cacAchievement.desc, cacAchievement.icon, cacAchievement.id, cacAchievement.points, cacAchievement.reward, cacAchievement.title)
                ProcessAchievement(aAchievement, cacAchievement)
                For Each cacCriteria As Schema.criteria In cacAchievement.criteria
                    aAchievement.AchievementCriteria.Add(New AchievementCriteria(cacCriteria.date, cacCriteria.id, cacCriteria.maxQuantity, cacCriteria.maxQuantityGold * 10000, cacCriteria.name, cacCriteria.quantity, cacCriteria.quantityGold * 10000 + cacCriteria.quantitySilver * 100 + cacCriteria.quantityCopper))
                Next
                cCategoryToProcess.Achievements.Add(aAchievement)
            Next
            For Each cacSubcategory As Schema.category In cacCategory.category
                Dim cSubcategory As New Category
                ProcessCategory(cSubcategory, cacSubcategory)
                cCategoryToProcess.Subcategories.Add(cSubcategory)
            Next
        End Sub

        Private Sub ProcessAchievement(ByRef aAchievement As Achievement, ByRef cacAchievement As Schema.achievement)
            For Each cacSubachievement As Schema.achievement In cacAchievement.achievement
                Dim aSubachievement As New Achievement(cacSubachievement.categoryId, cacSubachievement.dateCompleted, cacSubachievement.desc, cacSubachievement.icon, cacSubachievement.id, cacSubachievement.points, cacSubachievement.reward, cacSubachievement.title)
                ProcessAchievement(aSubachievement, cacSubachievement)
                For Each cacCriteria As Schema.criteria In cacSubachievement.criteria
                    aSubachievement.AchievementCriteria.Add(New AchievementCriteria(cacCriteria.date, cacCriteria.id, cacCriteria.maxQuantity, cacCriteria.maxQuantityGold * 10000, cacCriteria.name, cacCriteria.quantity, cacCriteria.quantityGold * 10000 + cacCriteria.quantitySilver * 100 + cacCriteria.quantityCopper))
                Next
                aAchievement.PreviousAchievements.Add(aSubachievement)
            Next
        End Sub

    End Class

End Namespace